package org.swan.plugin.beetl;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class CollectionFunction {
    /**
     * @param list
     * @param param split prefix suffix open close
     * @return
     */
    public String join(List<String> list, String... param) {
        StringBuilder sb = new StringBuilder();
        String[] tmp = new String[5];
        if (param != null)
            System.arraycopy(param, 0, tmp, 0, param.length);
        String splitStr = tmp[0] == null ? "" : tmp[0];
        String prefixStr = tmp[1] == null ? "" : tmp[1];
        String suffixStr = tmp[2] == null ? "" : tmp[2];
        String openStr = tmp[3] == null ? "" : tmp[3];
        String closeStr = tmp[4] == null ? "" : tmp[4];
        if (list == null)
            return openStr + closeStr;
        sb.append(openStr).append(list.stream().map(i -> prefixStr + i + suffixStr).collect(Collectors.joining(splitStr))).append(closeStr);
        return sb.toString();
    }

    public List<Object> attributeToList(Collection<?> list, String attribute) throws InvocationTargetException, IllegalAccessException {
        if (list == null || list.isEmpty() || attribute == null)
            return new ArrayList<>();
        Iterator iterator = list.iterator();
        Method m = null;
        Field field = null;
        List<Object> ret = new ArrayList<>();
        boolean first = true;
        while (iterator.hasNext()) {
            Object o = iterator.next();
            if (first) {
                String methodName = new CodeFunction().getter(attribute, false);
                try {
                    m = o.getClass().getDeclaredMethod(methodName);
                } catch (NoSuchMethodException ex) {

                }
                if (m == null) {
                    try {
                        m = o.getClass().getDeclaredMethod(new CodeFunction().getter(attribute, true));
                    } catch (NoSuchMethodException ex) {
                    }
                }
                if (m == null) {
                    try {
                        field = o.getClass().getDeclaredField(attribute);
                        field.setAccessible(true);
                    } catch (Exception ex) {

                    }
                }
                first = false;
            }
            if (m != null)
                ret.add(m.invoke(o));
            if (field != null)
                ret.add(field.get(o));
        }
        return ret;
    }

    public String updateStringList(Collection<String> columns, Collection<String> attributeName) {
        return updateString(collectionToArray(columns), collectionToArray(attributeName));
    }


    public String updateString(String[] columns, String[] attributeName) {
        if (columns == null)
            return "";
        String[] resultAttributes = fixArray(columns, attributeName);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < columns.length; i++) {
            sb.append(columns[i]).append(" = #{").append(resultAttributes[i]).append("} ,");
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public String insertStringList(Collection<String> columns, Collection<String> attributeName) {
        return insertString(collectionToArray(columns), collectionToArray(attributeName));
    }

    public String insertString(String[] columns, String[] attributeName) {
        if (columns == null)
            return "";
        String[] resultAttributes = fixArray(columns, attributeName);
        for (int i = 0; i < resultAttributes.length; i++) {
            resultAttributes[i] = "#{" + resultAttributes[i] + "}";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("( ").append(String.join(" , ", columns)).append(" ) VALUES ( ").append(String.join(" , ", resultAttributes)).append(")");
        return sb.toString();
    }


    private static String[] fixArray(String[] columns, String[] attributeName) {
        String[] resultAttributes = new String[columns.length];
        if (attributeName == null) {
            System.arraycopy(columns, 0, resultAttributes, 0, columns.length);
        } else {
            System.arraycopy(attributeName, 0, resultAttributes, 0, attributeName.length);
            if (attributeName.length < columns.length) {
                System.arraycopy(columns, attributeName.length, resultAttributes, attributeName.length, columns.length - attributeName.length);
            }
        }
        return resultAttributes;
    }

    private String[] collectionToArray(Collection<String> collection) {
        if (collection == null)
            return new String[0];
        return collection.toArray(new String[0]);
    }
}
